﻿#include "pch.h"
#include "hid_engine.h"
#include "TGSDK.h"
/**
 * 构造函数，用以构造出 hid_engine, hid_engine 包含编码器、解码器、以及线程池
 * @brief hid_engine::hid_engine
 * @param intf
 * @param _cfg
 */
hid_engine::hid_engine(std::shared_ptr<hid_interface> _hid_interface,
                       std::shared_ptr<config> _cfg)
    : hidInterface(_hid_interface), cfg(_cfg),
      encoder(std::make_shared<hid_encoder>(hidInterface, cfg)),
      decoder(std::make_shared<hid_decoder>(hidInterface, cfg)) {
  std::cout << "hid_engine: " << std::endl;
}

/**
 * 析构函数
 * @brief hid_engine::~hid_engine
 */
hid_engine::~hid_engine() {
  std::cout << "hid_engine::~hid_engine()" << std::endl;
  hidInterface.reset();
  cfg.reset();
}

/**
 * 打开设备
 * @brief hid_engine::open
 * @param vendor_id
 * @param product_id
 * @return
 */
int hid_engine::open(unsigned short vendor_id, unsigned product_id) {
  std::lock_guard<std::mutex> lock(g_Mutex);
  int ret;
  ret = hidInterface->open(vendor_id, product_id);
  if (!ret) {
    decoder->startDecoding();
  } else {
    decoder->stopDecoding();
  }
  INSTANCE(constants).setAckFlag(true);
  ack_cv_.notify_all();
  return ret;
}

/**
 * 关闭设备
 * @brief hid_engine::close
 * @return
 */
int hid_engine::close() {
  //  int ret;
  std::lock_guard<std::mutex> lock(g_Mutex);
  INSTANCE(constants).setAckFlag(true);
  ack_cv_.notify_all();
  try {
    decoder->stopDecoding();
    //    ret = hidInterface->close();
  } catch (std::exception &e) {
    // hid throw exception
  }

  return 0;
}

/**
 * 释放资源
 * @brief hid_engine::release
 * @return
 */
int hid_engine::release() {
  int ret;
  std::lock_guard<std::mutex> lock(g_Mutex);
  INSTANCE(constants).setAckFlag(true);
  ack_cv_.notify_all();
  try {
    decoder->stopDecoding();
    //    ret = hidInterface->close();
  } catch (std::exception &e) {
    // hid throw exception
  }

  return 0;
}

/**
 * 下位机发送心跳包，回复下位机已正确收到
 * @brief hid_engine::writePongData
 */
void hid_engine::writePongData() {
  std::lock_guard<std::mutex> lock(g_Mutex);
  std::vector<char> data;
  data.insert(data.begin(), 0x00);
  std::string tag("test");
  writePingPong(data.data(), data.size(), (char *)tag.data(), tag.size(),
                CMD_PING_PONG);

#if _DEBUG
  std::cout << "Send PONG..." << std::endl;
#endif
}

/**
 * 写数据，写完数据后等待使用同步锁等待下位机的 ACK 指令
 * @brief hid_engine::writeData
 * @param data 数据，utf-8编码
 * @param size 数据长度
 * @param tag  包标签, utf-8编码
 * @param tagSize 包标签长度
 * @param cmd  命令类型，目前支持 CMD_TEXT（文本）、CMD_FILE(文件)
 * @return
 */
int hid_engine::writeDataSync(const char *data, int size, const char *tag,
                              int tagSize, char cmd) {
  {
    std::lock_guard<std::mutex> lock(g_Mutex);
    sendState = TEXT;
    this->mHIDWriteListener = std::weak_ptr<OnHIDWriteListener>();
    // 如果 ，需要等待释放为 true

    if (!INSTANCE(constants).getAckFlag()) {
      std::cout << u8"ACK未正确处理..." << std::endl;
      return false;
    }
    INSTANCE(constants).setAckFlag(false);
    if (encoder == nullptr) {
      return false;
    }
  }
  bool ret = encoder->writeDataSync(data, size, tag, tagSize, cmd);
  if (ret) {
    std::unique_lock<mutex> lock(ack_mutex_);
    std::cout << "==========================" << std::endl;
    std::cout << "writeDataSync wait ack response: " << std::endl;
    // 等待 ACK 回复
    ret =
        ack_cv_.wait_for(lock, std::chrono::milliseconds(ACK_RESPONSE_TIMEOUT),
                         [] { return INSTANCE(constants).getAckFlag(); });
    std::cout << "writeDataSync ack response:" << std::endl;
    if (!ret) {
      return ERR_TIMEOUT;
    }
    return ret ? ERR_SUCCESS : ERR_DEVICE_FAIL;
  }
  return ret ? ERR_SUCCESS : ERR_DEVICE_FAIL;
}

/**
 * 内部写数据方法，用于发送 ACK 数据
 * @brief hid_engine::writeDataInner
 * @param data 数据，utf-8编码
 * @param size 数据长度
 * @param tag  包标签, utf-8编码
 * @param tagSize 包标签长度
 * @return
 */
bool hid_engine::WriteACK(const char *data, int size, const char *tag,
                          int tagSize, char cmd) {
  {
    std::lock_guard<std::mutex> lock(g_Mutex);
    sendState = TEXT;
    if (encoder == nullptr) {
      return false;
    }
  }

  return encoder->writeDataSync(data, size, tag, tagSize, cmd);
}

/**
 * 写心跳包
 * @brief hid_engine::writePingPong
 * @param data
 * @param size
 * @param tag
 * @param tagSize
 * @param cmd
 * @return
 */
bool hid_engine::writePingPong(const char *data, int size, const char *tag,
                               int tagSize, char cmd) {
  sendState = TEXT;
  return encoder->writeDataSync(data, size, tag, tagSize, cmd);
}

/**
 * 写数据
 * @brief hid_engine::writeData
 * @param data 数据，utf-8编码
 * @param size 数据长度
 * @param tag  包标签, utf-8编码
 * @param tagSize 包标签长度
 * @param cmd  命令类型，目前支持 CMD_TEXT（文本）、CMD_FILE(文件)
 * @param l    写数据监听回调
 * @return
 */
void hid_engine::writeData(const char *data, int size, const char *tag,
                           int tagSize, char cmd,
                           std::weak_ptr<OnHIDWriteListener> l) {
  {
    std::lock_guard<std::mutex> lock(g_Mutex);
    sendState = TEXT;
    this->mHIDWriteListener = l;
    // 如果 ACK 未正确处理，需要等待释放为 true
    //    if (!INSTANCE(constants).getAckFlag()) {
    //      if (l.lock() != nullptr) {
    //        l.lock()->onHIDWriteFailed(HID_WRITE_ERROR, "No Ack response.");
    //      }
    //      return;
    //    }
    //    INSTANCE(constants).setAckFlag(false);
    if (encoder == nullptr) {
      return;
    }
  }
  encoder->writeData(data, size, tag, tagSize, cmd, l);
}

/**
 * 写文件
 * @brief hid_engine::writeFile
 * @param filePath 文件路径，utf-8编码
 * @param tag      包标签,utf-8编码
 * @param tagSize 包标签长度
 * @param l   监听写操作结果
 * @return
 */
void hid_engine::writeFile(const std::string &filePath, const char *tag,
                           int tagSize, std::weak_ptr<OnHIDWriteListener> l) {
  {
    std::lock_guard<std::mutex> lock(g_Mutex);
    sendState = FILE;
    //    this->mHIDWriteListener = l;
    // 如果 ACK 未正确处理，需要等待释放为 true
    //    if (!INSTANCE(constants).getAckFlag()) {
    //      if (l.lock() != nullptr) {
    //        l.lock()->onHIDWriteFailed(HID_WRITE_ERROR, "No Ack response.");
    //      }
    //      return;
    //    }
    //    INSTANCE(constants).setAckFlag(false);
    if (encoder == nullptr) {
      return;
    }
  }
  encoder->writeFile(filePath, tag, tagSize, l);
}

/**
 * 写文件
 * @brief hid_engine::writeFile
 * @param filePath 文件路径，utf-8编码
 * @param tag      包标签,utf-8编码
 * @param tagSize 包标签长度
 * @return
 */
void hid_engine::writeFile(const std::string &filePath, const char *tag,
                           int tagSize) {
  {
    std::lock_guard<std::mutex> lock(g_Mutex);
    sendState = FILE;
    //    this->mHIDWriteListener = std::weak_ptr<OnHIDWriteListener>();
    // 如果 ACK 未正确处理，需要等待释放为 true
    //    if (!INSTANCE(constants).getAckFlag()) {
    //      return;
    //    }
    //    INSTANCE(constants).setAckFlag(false);
    if (encoder == nullptr) {
      return;
    }
  }
  encoder->writeFile(filePath, tag, tagSize,
                     std::weak_ptr<OnHIDWriteListener>());
}

/**
 * 写随机文件
 * @param filePath
 * @param tag
 * @param tagSize
 * @param l
 */
void hid_engine::writeRandomFile(
    const string &filePath, int fileExtension,
    std::weak_ptr<OnHIDWriteRandomFileListener> l) {
  {
    std::lock_guard<std::mutex> lock(g_Mutex);
    sendState = RANDOM_FILE;
    //    this->mHIDWriteRandomFileListener = l;
    // 如果 ACK 未正确处理，需要等待释放为 true
    //    if (!INSTANCE(constants).getAckFlag()) {
    //      if (l.lock() != nullptr) {
    //        l.lock()->onHIDWriteRandomFailed(HID_WRITE_ERROR, "No Ack
    //        response.");
    //      }
    //      return;
    //    }
    //    INSTANCE(constants).setAckFlag(false);
    if (encoder == nullptr) {
      return;
    }
  }
  encoder->writeRandomFile(filePath, fileExtension, l);
}

/**
 * 获取下载文件路径 utf-8编码
 * @brief hid_engine::getDownloadFilePath
 * @return
 */
std::string hid_engine::getDownloadFilePath() const {
  if (decoder == nullptr) {
    return "";
  }
  return decoder->getDownloadFilePath();
}

void hid_engine::cancelRandomFile() {
  if (encoder != nullptr) {
    encoder->cancelRandomFile();
  }
}

void hid_engine::stopRandomFile() {
  if (encoder != nullptr) {
    encoder->stopRandomFile();
  }
}

void hid_engine::pause() {
  if (encoder != nullptr) {
    encoder->pause();
  }
}

void hid_engine::resume() {
  if (encoder != nullptr) {
    encoder->resume();
  }
}

/**
 * 停止发送数据
 * @brief hid_engine::stop
 * @param l
 * @return
 */
bool hid_engine::stop(std::weak_ptr<OnHIDStopDataListener> l) {
  return encoder->stop(l);
}

/**
 * HID错误监听器
 * @brief hid_engine::setOnHIDErrorListener
 * @param l
 */
void hid_engine::setOnHIDErrorListener(std::weak_ptr<OnHIDErrorListener> l) {
  if (decoder != nullptr) {
    decoder->setOnHIDErrorListener(l);
  }
}

/**
 * 设置 HID 传输帧数据监听
 * @brief hid_engine::setOnHIDFrameListener
 * @param l
 */
void hid_engine::setOnHIDFrameListener(std::weak_ptr<OnHIDFrameListener> l) {
  if (decoder != nullptr) {
    mHIDFrameListener = l;
    decoder->setOnHIDFrameListener(std::weak_ptr<OnHIDFrameListener>(l));
  }
}

/**
 * 设置HID文件传输监听
 * @brief hid_engine::setOnHIDReadFileListener
 * @param l
 */
void hid_engine::setOnHIDReadFileListener(
    std::weak_ptr<OnHIDReadFileListener> l) {
  if (decoder != nullptr) {
    decoder->setOnHIDReadFileListener(l);
  }
}

/**
 * 设置随机文件读取监听
 * @brief hid_engine::setOnHIDRandomFileListener
 * @param l
 */
void hid_engine::setOnHIDReadRandomFileListener(
    std::weak_ptr<OnHIDReadRandomFileListener> l) {
  if (decoder != nullptr) {
    decoder->setOnHIDReadRandomFileListener(l);
  }
}

/**
 * 设置读上位机随机文件
 * @param l
 */
void hid_engine::setOnReadRandomFileListener(
    std::weak_ptr<OnHIDReadRandomFileListener> l) {
  if (decoder != nullptr) {
    decoder->setOnHIDReadRandomFileListener(l);
  }
}

/**
 * 监听停止事件
 * @brief hid_engine::setOnHIDStopListener
 * @param l
 */
void hid_engine::setOnHIDStopListener(std::weak_ptr<OnHIDStopDataListener> l) {
  if (decoder != nullptr) {
    encoder->stop(l);
  }
}
